# This file is part of OrangeSpider. OrangeSpider is a meta model based
# development tool.
# 
# OrangeSpider is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# OrangeSpider is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with OrangeSpider.  If not, see <http://www.gnu.org/licenses/>.
#
# Copyright 2009 Stefan Nikolaus <OrangeSpiderMaster@googlemail.com>

from MetaModel import *
import Algorithms
from Ui import *
from Builder import *
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import Component

class FastEditTab(QWidget):
    def __init__(self, root, navigator, selector, parent=None):
        QTabWidget.__init__(self, parent)
        self.root = root
        self.navigator = navigator

        self.view = RepositoryTableView(root, navigator, 
                                        selector, Table.ModeExtend, self)
        layout = QGridLayout(self)
        layout.addWidget(self.view, 0, 0)
        self.setLayout(layout)

        self.connect(self.view, SIGNAL("doubleClicked(const QModelIndex & )"), 
                     self.view_doubleClicked)

    def view_doubleClicked(self, index):
        # Get class
        item = self.view.model().data(index, Table.ViewDataRole)
        self.emit(SIGNAL("navigateRequest"), item)


class FastEditTabExtension(FastEditTab):
    def __init__(self, root, navigator, parent=None):
        FastEditTab.__init__(self, root, "Extension", "", parent)
        assert(root.isMetaClass())

    def name(self):
        return self.root["Name"]
    

class FastEditTabOutgoing(FastEditTab):
    def __init__(self, root, navigator, selector, parent=None):
        FastEditTab.__init__(self, root, navigator, selector, parent)
        self.selector = selector
        assert(root.isClass())

    def name(self):
        return self.selector

class FastEditTabReference(FastEditTab):
    def __init__(self, root, parent=None):
        QTabWidget.__init__(self, parent)
        self.root = root
        assert(root.isClass())

        layout = QGridLayout(self)
        row = 0
        for ma in root.intention.eachOutgoingMetaAssoc():
            if ma["TargetCardinality"] in [ONE, OPTIONAL]:
                view = ReferenceComboBox(root, ma, self)

                label = QLabel(ma["Name"])
                layout.addWidget(label, row, 0)
                layout.addWidget(view, row, 1)
                row += 1
                self.connect(view, SIGNAL("navigateRequest"), 
                             self._doNavigate)

        self.setLayout(layout)

    def _doNavigate(self, item):
        self.emit(SIGNAL("navigateRequest"), item)

    def name(self):
        return "References"

class FastEditTabAssociations(FastEditTab):
    def __init__(self, root, navigator, selector, parent=None):
        QTabWidget.__init__(self, parent)
        self.root = root
        assert(root.isClass())
        assert(navigator == "OutgoingClasses") # Incoming later
        self.selector = selector
        layout = QGridLayout(self)
        ma = root.intention.outgoing[selector]
        self.viewExt = RepositoryTableView(ma.target, "Extension", "", Table.ModeView, self)

        self.viewSelection = RepositoryTableView(root, navigator, selector, Table.ModeView, self)
        self.connect(self.viewSelection, 
                     SIGNAL("doubleClicked(const QModelIndex & )"), 
                     self.view_doubleClicked)

        l = QVBoxLayout()
        addButton = QPushButton("->")
        removeButton = QPushButton("<-")
        l.addWidget(addButton)
        l.addWidget(removeButton)
        self.connect(addButton, SIGNAL("clicked()"), 
                     self.addButton_clicked)
        self.connect(removeButton, SIGNAL("clicked()"), 
                     self.removeButton_clicked)

        layout.addWidget(self.viewExt, 0, 0)
        layout.addLayout(l, 0, 1)
        layout.addWidget(self.viewSelection, 0, 2)
        self.setLayout(layout)

    def view_doubleClicked(self, index):
        # Get class
        item = self.viewSelection.model().data(index, Table.ViewDataRole)
        self.emit(SIGNAL("navigateRequest"), item)

    def addButton_clicked(self):
        selectedRows = self.viewExt.selectionModel().selectedRows()
        for s in selectedRows:
            repOb = self.viewExt.model().data(s, Table.KeyDataRole)
            #repOb = s.internalPointer()
            r = repOb.metaModel()
            r.Assoc(self.root, repOb, self.selector)

    def removeButton_clicked(self):
        selectedRows = self.viewSelection.selectionModel().selectedRows()
        for s in selectedRows:
            repOb = self.viewSelection.model().data(s, Table.KeyDataRole)
            #repOb = s.internalPointer()
            r = repOb.metaModel()
            r.deleteAssoc(repOb)

    def name(self):
        return self.selector


class FastEditDlg(QDialog):
    def __init__(self, entity, parent=None):
        QDialog.__init__(self, parent)

        self.setWindowTitle("FastEdit")
        self.setLayout(QGridLayout(self))
        self.propertyView = None
        self.tab = None
        self.navigateStack = []
        self.header = QLabel()
        font = QFont("Helvetica", 14, QFont.Bold)
        self.header.setFont(font)
        self.layout().addWidget(self.header, 0, 0)

        self.backButton = QPushButton("Back")
        l = QHBoxLayout()
        l.addStretch()
        l.addWidget(self.backButton)
        self.layout().addLayout(l, 0, 1)
        #self.layout().addWidget(self.backButton, 0, 1)
        self.connect(self.backButton, SIGNAL("clicked()"), 
                     self.moveBack)

        self.navigateRequest(entity)
        self.setWindowIcon(QIcon("img/spiderIco.png"))


    def navigateRequest(self, entity):
        if not entity:
            return
        assert(entity.isMetaModel() or entity.isClass())

        if self.tab:
            currTabId = self.tab.currentIndex()
        else:
            currTabId = 0
        self.navigateStack.append( (entity, currTabId) )
        if len(self.navigateStack) > 1:
            self.backButton.setEnabled(1)
        else:
            self.backButton.setEnabled(0)

        if self.propertyView:
            self.propertyView.deleteLater()
            self.propertyView = None

        if self.tab:
            self.tab.deleteLater()
            self.tab = None

        self.propertyView = RepositoryTableView(entity, "Properties", "", Table.ModeEdit)
        self.layout().addWidget(self.propertyView, 1, 0, 1, 2)

        self.repository = entity.metaModel()

        self.tab = QTabWidget(self)
        if entity.isMetaModel():
            # Setup FastEdit for MetaModel (start screen)
            self.header.setText(entity["Name"] + " (" + entity["Type"] + ")")
            list = Algorithms.getNonAggregatedMetaClasses(entity)
            for mcName in list:
                mc = self.repository.metaClasses[mcName]
                w = FastEditTabExtension(mc, self)
                self.tab.addTab(w, w.name())
                self.connect(w, SIGNAL("navigateRequest"), 
                             self.navigateRequest)

        elif entity.isClass():
            if "Name" in entity:
                s = entity["Name"]
            else:
                s = str(entity["Id"])
            self.header.setText(s + " (" + entity.intention["Name"] + ")")
            hasRef = 0
            for ma in entity.intention.eachOutgoingMetaAssoc():
                if ma["Aggregation"]:
                    w = FastEditTabOutgoing(entity, "OutgoingClasses", 
                                            ma["Name"], self)
                    self.tab.addTab(w, w.name())
                    self.connect(w, SIGNAL("navigateRequest"), 
                                 self.navigateRequest)
                if ma["TargetCardinality"] in [ONE, OPTIONAL]:
                    hasRef = 1
                if ma["TargetCardinality"] == MANY:
                    if ma["SourceCardinality"] == MANY:
                        assert(ma["Aggregation"] == 0)
                        w = FastEditTabAssociations(entity, "OutgoingClasses", 
                                                    ma["Name"], self)
                        self.tab.addTab(w, w.name())
                        self.connect(w, SIGNAL("navigateRequest"), 
                                     self.navigateRequest)

            if hasRef:
                w = FastEditTabReference(entity, self)
                self.tab.addTab(w, w.name())
                print self.connect(w, SIGNAL("navigateRequest"), 
                                   self.navigateRequest)

        else:
            # not implemented
            assert(0)

        self.layout().addWidget(self.tab, 2, 0, 1, 2)

    def moveBack(self):
        (current, currTabId) = self.navigateStack.pop()
        (oldTarget, oldTabId) = self.navigateStack.pop()
        #print currTabId, oldTabId
        self.navigateRequest(oldTarget)
        self.tab.setCurrentIndex(currTabId)


class FastEdit(Component.Component):
    def __init__(self):
        Component.Component.__init__(self)

    def interface(self, interfaceName):
        if interfaceName == "Spider.IProject":
            return self
        elif interfaceName == "Spider.IManagedComponent":
            return self
        return None

    # Interface Spider.IProject
    def open(self, project, r, item):
        self.project = project
        self.projectItem = item
        self.fe = FastEditDlg(r)
        self.fe.show()

    # Interface Spider.IManagedComponent
    @staticmethod
    def setupComponentType(rSpiderCOMP):
        return Component.Component._setupComponentType(rSpiderCOMP , "Spider.FastEdit.FastEdit",
                                                       "Shows the fast edit editor",
                                                       1, ["Spider.IProject", "Spider.IManagedComponent"])


if __name__ == "__main__":
    app = QApplication(sys.argv)

    if 0:
        r2 = buildMetaModel("MetaModel", "SpiderINI")
        mmc = Component.MetaModelConverter()
        r = mmc.extract(r2)

    if 0:
        iniComp = Component.IniFileReader()
        iniComp.read("xtcpmon.ini")    
        r = iniComp.repository

    if 0:
        di = Component.DirectoryImporter()
        r = di.repository

    if 1:
        r = buildMetaModel("SQL", "SpiderSQL")

    r.watcher = Watcher()
    emitter = r.watcher.addListener(Emitter(), "Emitter")
    #r.watcher.emitter = Emitter()

    fe = FastEditDlg(r)
    fe.show()

    app.exec_()


    sys.exit(0)

